use calamine::{open_workbook, Reader, Xlsx};
use clap::Parser;
use indicatif::{ProgressBar, ProgressStyle};
use rust_xlsxwriter::Workbook;
use std::collections::HashMap;
use std::path::PathBuf;

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    #[arg(long)]
    input: Vec<String>,
    #[arg(long)]
    output: String,
    #[arg(long)]
    rule: String,
}

fn main() {
    let args = Args::parse();
    let inputs: Vec<_> = args.input;
    let output = args.output;
    let merge_rule = args.rule;

    let bar = ProgressBar::new(inputs.len() as u64);
    bar.set_style(
        ProgressStyle::with_template(
            "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})",
        )
        .unwrap()
        .progress_chars("#>-"),
    );

    let mut wb = Workbook::new();

    let mut sheets_data: HashMap<usize, Vec<Vec<String>>> = HashMap::new();

    // Parse merge rule
    let rule_parts: Vec<&str> = merge_rule.split('=').collect();
    let file1_column: Vec<&str> = rule_parts[0].split(':').collect();
    let file2_column: Vec<&str> = rule_parts[1].split(':').collect();

    let file1_index = file1_column[0][5..file1_column[0].len() - 1]
        .parse::<usize>()
        .unwrap()
        - 1;
    let file2_index = file2_column[0][5..file2_column[0].len() - 1]
        .parse::<usize>()
        .unwrap()
        - 1;

    for (index, file) in inputs.iter().enumerate() {
        let mut excel: Xlsx<_> = open_workbook(PathBuf::from(file)).unwrap();

        if let Some(Ok(r)) = excel.worksheet_range("Sheet1") {
            let mut sheet_data = vec![];

            for row in r.rows() {
                let mut row_data = vec![];
                for cell in row {
                    row_data.push(cell.to_string());
                }
                sheet_data.push(row_data);
            }

            sheets_data.insert(index, sheet_data);
        }
        bar.inc(1);
    }
    bar.finish();

    let ws = wb.add_worksheet();
    ws.set_name("Merged").unwrap();

    let sheet1_data = sheets_data.get(&file1_index).unwrap();
    let sheet2_data = sheets_data.get(&file2_index).unwrap();

    let mut row_num = 0;
    for (i, row) in sheet1_data.iter().enumerate() {
        for cell in row {
            ws.write(row_num, i as u16, cell).unwrap();
        }
        row_num += 1;
    }

    let file1_col_index = file1_column[1].chars().next().unwrap() as u32 - 'A' as u32;
    let file2_col_index = file2_column[1].chars().next().unwrap() as u32 - 'A' as u32;
    for (i, row) in sheet2_data.iter().enumerate() {
        if sheet1_data[i][file1_col_index as usize] == row[file2_col_index as usize] {
            for cell in row {
                ws.write(row_num, i as u16, cell).unwrap();
            }
            row_num += 1;
        }
    }

    wb.save(output).unwrap();
}
